/*
 * defs.h
 *
 * Copyright (C) 2017 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __MONOLITHIUM_DEFS_H__
#define __MONOLITHIUM_DEFS_H__

#include <limits.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>

#define FALSE 0
#define TRUE (!FALSE)
#define VARIABLE_SIZE 0

/* Monolithium-specific Type Limits */
#define BYTE_MIN  0
#define BYTE_MAX  0xFF
#define WORD_MIN  0
#define WORD_MAX  0xFFFF
#define DWORD_MIN 0
#define DWORD_MAX 0xFFFFFFFF
#define QWORD_MIN 0ULL
#define QWORD_MAX 0xFFFFFFFFFFFFFFFFULL

/* Monolithium Error Codes */
#define ERR_SUCCESS   0x00000000
#define ERR_NOTFOUND  0xE0000001
#define ERR_FORBIDDEN 0xE0000002
#define ERR_INVALID   0xE0000003
#define ERR_EXISTS    0xE0000004
#define ERR_NOMEMORY  0xE0000005
#define ERR_HARDWARE  0xE0000006
#define ERR_BUSY      0xE0000007
#define ERR_WRITEPROT 0xE0000008
#define ERR_NOSYSCALL 0xE0000009
#define ERR_TIMEOUT   0xE000000A
#define ERR_BADPTR    0xE000000B
#define ERR_CANCELED  0xE000000C
#define ERR_ISDIR     0xE000000D
#define ERR_ISNOTDIR  0xE000000E
#define ERR_DISKFULL  0xE000000F
#define ERR_BEYOND    0xE0000010
#define ERR_SMALLBUF  0xE0000011
#define ERR_NOMORE    0xE0000012
#define MAX_ERR       0xE0000013

#define MAX_PATH 16384
#define NO_TIMEOUT 0xFFFFFFFF

#define UNUSED_PARAMETER(x) (x)=(x)
#define OFFSET_OF(type, field) ((uintptr_t)(&((type*)NULL)->field))
#define CONTAINER_OF(ptr, type, field) ((type*)((uintptr_t)(ptr) - OFFSET_OF(type, field)))

/* Monolithium-specific Types */
typedef uint8_t bool_t;
typedef uint8_t byte_t;
typedef uint16_t word_t;
typedef uint32_t dword_t;
typedef uint64_t qword_t;

/* System call return value */
typedef dword_t sysret_t;

typedef dword_t timeout_t;

static inline void set_bit(dword_t *bitfield, dword_t bit)
{
    bitfield[bit >> 5] |= 1 << (bit & 0x1F);
}

static inline void clear_bit(dword_t *bitfield, dword_t bit)
{
    bitfield[bit >> 5] &= ~(1 << (bit & 0x1F));
}

static inline bool_t test_bit(dword_t *bitfield, dword_t bit)
{
    return (bitfield[bit >> 5] & (1 << (bit & 0x1F))) ? TRUE : FALSE;
}

static inline void push_to_stack(uintptr_t *stack, uintptr_t value)
{
    *stack -= sizeof(uintptr_t);
    *((uintptr_t*)(*stack)) = value;
}

static inline uintptr_t pop_from_stack(uintptr_t *stack)
{
    uintptr_t value = *((uintptr_t*)(*stack));
    *stack += sizeof(uintptr_t);
    return value;
}

static inline const char *get_error_string(dword_t err_num)
{
    static const char *error_strings[] = {
        "ERR_SUCCESS",
        "ERR_NOTFOUND",
        "ERR_FORBIDDEN",
        "ERR_INVALID",
        "ERR_EXISTS",
        "ERR_NOMEMORY",
        "ERR_HARDWARE",
        "ERR_BUSY",
        "ERR_NOMEDIA",
        "ERR_NOTRESP",
        "ERR_WRITEPROT",
        "ERR_NOSYSCALL",
        "ERR_TIMEOUT",
        "ERR_BADPTR",
        "ERR_CANCELED",
        "ERR_ISDIR",
        "ERR_ISNOTDIR",
        "ERR_DISKFULL",
        "ERR_MEDIACHG"
    };

    if (err_num == 0)
    {
        return error_strings[0];
    }
    else if (err_num >= 0xE0000000)
    {
        if (err_num < MAX_ERR) return error_strings[err_num - 0xE0000000];
    }

    return NULL;
}

#endif
